package com.inspur.edp.formserver.vmmanager.validate;


import com.alibaba.druid.util.StringUtils;
import com.inspur.edp.bef.bizentity.GspBizEntityElement;
import com.inspur.edp.bef.bizentity.GspBusinessEntity;
import com.inspur.edp.bef.bizentity.operation.BizActionBase;
import com.inspur.edp.bef.bizentity.operation.BizMgrAction;
import com.inspur.edp.bef.bizentity.operation.BizOperation;
import com.inspur.edp.bef.bizentity.operation.collection.BizMgrActionCollection;
import com.inspur.edp.bef.bizentity.operation.componentinterface.IBizParameter;
import com.inspur.edp.bef.component.ICompParameter;
import com.inspur.edp.bef.component.ICompParameterCollection;
import com.inspur.edp.bef.component.base.GspComponent;
import com.inspur.edp.bef.component.base.ReturnValue;
import com.inspur.edp.bef.component.detailcmpentity.vm.VMComponent;
import com.inspur.edp.cef.designtime.api.IGspCommonField;
import com.inspur.edp.cef.designtime.api.collection.CommonDtmCollection;
import com.inspur.edp.cef.designtime.api.element.ElementDefaultVauleType;
import com.inspur.edp.cef.designtime.api.element.GspElementDataType;
import com.inspur.edp.cef.designtime.api.element.GspElementObjectType;
import com.inspur.edp.cef.designtime.api.element.GspEnumValue;
import com.inspur.edp.cef.designtime.api.operation.CommonDetermination;
import com.inspur.edp.cef.designtime.api.operation.CommonOperation;
import com.inspur.edp.cef.designtime.api.variable.CommonVariableCollection;
import com.inspur.edp.das.commonmodel.IGspCommonElement;
import com.inspur.edp.das.commonmodel.IGspCommonObject;
import com.inspur.edp.das.commonmodel.entity.GspCommonModel;
import com.inspur.edp.das.commonmodel.entity.object.GspCommonObjectType;
import com.inspur.edp.formserver.viewmodel.GspViewModel;
import com.inspur.edp.formserver.viewmodel.GspViewModelElement;
import com.inspur.edp.formserver.viewmodel.GspViewObject;
import com.inspur.edp.formserver.viewmodel.action.*;
import com.inspur.edp.formserver.viewmodel.action.viewmodelbase.ViewModelReturnValue;
import com.inspur.edp.formserver.viewmodel.collection.VMActionCollection;
import com.inspur.edp.formserver.viewmodel.collection.ValueHelpConfigCollection;
import com.inspur.edp.formserver.viewmodel.common.VMParameterType;
import com.inspur.edp.formserver.viewmodel.common.ValueHelpConfig;
import com.inspur.edp.formserver.viewmodel.common.mapping.GspVoElementSourceType;
import com.inspur.edp.formserver.viewmodel.common.mapping.GspVoObjectSourceType;
import com.inspur.edp.formserver.vmmanager.exception.VmManagerException;
import com.inspur.edp.formserver.vmmanager.service.VmManagerService;
import com.inspur.edp.formserver.vmmanager.util.CheckInfoUtil;
import com.inspur.edp.formserver.vmmanager.util.ExpressionVariableCheckUtil;
import com.inspur.edp.lcm.metadata.api.entity.GspMetadata;
import com.inspur.edp.lcm.metadata.api.service.RefCommonService;
import io.iec.edp.caf.commons.exception.ExceptionLevel;
import io.iec.edp.caf.commons.utils.SpringBeanUtils;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.function.Predicate;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

public class ViewModelValidator {

  private String errorCode = "ViewModelValidate";
  private GspViewModel vm;
  private String metaPath;
  private GspBusinessEntity be;
  private static final String OPT_CDPACTION = "视图对象操作";
  private static final String FIELD = "对象 '%1$s' 的字段 '%2$s' ";
  private static final String VARIABLE = "模型%1$s'变量集合' 的字段 '{%2$s}' ";
  private static final String VARIABLE_DTM = "'变量集合' 的联动计算 ";
  private static final String VALUEHELPCONFIG = "'帮助集合' 的帮助信息";
  private static final String VALUEHELPACTION = "'帮助集合' 的帮助 '{%1$s}'中的帮助前事件操作 ";
  private static final String EXPRESSION = "'{%1$s}' 的字段 '{%2$s}' ";

  private void throwValidateException(String message) {
    throw new VmManagerException("", errorCode, message, null, ExceptionLevel.Error, false);
  }

  public final boolean validate(String path, GspViewModel vm) {
    this.vm = vm;
    this.metaPath = path;
    if (!vm.getIsVirtual()
        && vm.getMainObject().getMapping().getSourceType() == GspVoObjectSourceType.BeObject) {

      GspMetadata dto = SpringBeanUtils.getBean(RefCommonService.class)
          .getRefMetadata(vm.getMapping().getTargetMetadataId());
      if (dto == null || dto.getContent() == null) {
        throwValidateException("获取映射的业务实体失败，id=" + vm.getMapping().getTargetMetadataId());
      }
      be = (GspBusinessEntity) ((dto.getContent() instanceof GspBusinessEntity) ? dto.getContent()
          : null);
    }
    return validateModel() && validateObject() && validateElement() && validateVmActions()
        && validateDataExtendInfo() && validateHelpActions();
  }


  ///#region 模型
  private boolean validateModel() {
    boolean validateRez = true;
    //检查父子关联字段

    String valRes = validateModelBasicInfo(vm);
    if(!StringUtils.isEmpty(valRes)){
      throwValidateException(valRes);
    }
    ArrayList<IGspCommonObject> objList = vm.getAllObjectList();
    StringBuilder sb = new StringBuilder();

    for (IGspCommonObject item : objList) {
      if (item.getObjectType() == GspCommonObjectType.MainObject) //不检查主对象
      {
        continue;
      }
      if (item.getKeys().size() == 0 || CheckInfoUtil
          .checkNull(item.getKeys().get(0).getSourceElement()) || CheckInfoUtil
          .checkNull(item.getKeys().get(0).getTargetElement())) {
        sb.append(item.getName()).append(",");
      }
    }
    if (sb.length() > 0) {
      sb.setLength(sb.length() - 1);
      throwValidateException(
          String.format("以下子对象的关联信息不完整，请修改后再保存：%1$s%2$s", "\r\n", sb.toString()));
      validateRez = false;
    }

    // 变量实体
    String message = validateVarableEntity(vm);
    if (message.length() > 0) {
      throwValidateException(message);
      validateRez = false;
    }

    // 帮助前事件
    message = validateValueHelpConfigs(vm);
    if (message.length() > 0) {
      throwValidateException(message);
      validateRez = false;
    }
    return validateRez;
  }

  private String validateModelBasicInfo(GspViewModel model) {
    StringBuilder sb = new StringBuilder();
    if (CheckInfoUtil.checkNull(model.getCode())) {
      sb.append(String.format("视图对象[%1$s]的编号不能为空! ", model.getName()));
    } else {
      // 模型Code限制非法字符
      if (!ConformToNaminGspecification(model.getCode())) {
        sb.append(String.format("视图对象[%1$s]的 [编号] 属性必须以英文字母或下划线开头, 并且只能由英文字母、数字、下划线(_)组成! ", model.getName()));
        sb.append("\n");
      }
    }
    if (CheckInfoUtil.checkNull(model.getName())) {
      sb.append(String.format("视图对象[%1$s]的名称不能为空! ", model.getCode()));
    }
    return sb.toString();
  }

  /**
   * 是否符合命名规范
   * 字母数字下划线组成,字母下划线开头
   *
   * @param text
   * @return
   */
  private boolean ConformToNaminGspecification(String text) {
    String regex = "^[A-Za-z_][A-Za-z_0-9]*$";
    Pattern pattern = Pattern.compile(regex);
    Matcher matcher = pattern.matcher(text);
    boolean ismatch = matcher.matches();
    return ismatch;
  }

  private String validateVarableEntity(GspCommonModel model) {
    StringBuilder sb = new StringBuilder();
    //validateObjectBasicInfo(model.Variables,sb,model.Name);
    sb.append(validateVariables(model));
    return sb.toString();
  }

  private String validateVariables(GspCommonModel model) {

    CommonVariableCollection vars = model.getVariables().getContainElements();
    StringBuilder sb = new StringBuilder();
    if (vars != null && vars.size() > 0) {

      for (IGspCommonField variable : vars) {
        // 检查元素的基本信息
        validateElementBasicInfo(variable, sb, model.getVariables().getName(), VARIABLE);
      }

      // 编号不可重复
      for (int i = 0; i < vars.size() - 1; i++) {
        IGspCommonField firstElement = vars.getItem(i);
        for (int j = i + 1; j < vars.size(); j++) {
          IGspCommonField secondElement = vars.getItem(j);
          if (firstElement.getCode().equals(secondElement.getCode())
              && firstElement.getBelongObject().getID().equals(secondElement.getBelongObject()
              .getID())) {
            String message = String
                .format("模型 '%1$s' 的'变量集合' 中字段 '%2$s' 和字段 '%3$s' 的 [编号] 属性不允许重复! ", model.getName(),
                    firstElement.getName(), secondElement.getName());
            return message;
          }
        }
      }
    }

    //联动计算
    CommonDtmCollection dtms = new CommonDtmCollection();
    dtms.addAll(model.getVariables().getDtmAfterCreate());
    dtms.addAll(model.getVariables().getDtmAfterModify());
    dtms.addAll(model.getVariables().getDtmBeforeSave());
    sb.append(validateVarDtms(dtms, model.getName()));

    return sb.toString();
  }

  private String validateVarDtms(CommonDtmCollection collection, String modelName) {
    //联动计算
    ArrayList<CommonOperation> dtms = (ArrayList<CommonOperation>) collection.stream()
        .map(item -> (CommonOperation) item).collect(
            Collectors.toList());
//		CommonDetermination[] dtms = (CommonDetermination[]) collection.toArray();
    //①必填项
    StringBuilder sb = new StringBuilder();
    sb.append(String.format(validateCommonOperationBasicInfo(VARIABLE_DTM, dtms)));
    if (sb.length() > 0) {
      return sb.toString();
    }
    //②编号重复
    sb.append(String.format(validateCommonOperationCodeRepeat(VARIABLE_DTM, dtms)));
    return sb.toString();
  }

  ///#endregion

  ///#region 对象

  /**
   * 校验对象基本信息
   */
  private boolean validateObject() {
    boolean validateRez = true;
    StringBuilder sb = new StringBuilder();

    ArrayList<IGspCommonObject> aObjectList = vm.getAllObjectList();

    //编号名称不允许为空
    for (IGspCommonObject aObject : aObjectList) {
      if (CheckInfoUtil.checkNull(aObject.getCode())) {
        sb.append(String.format("对象 '%1$s' 的编号不能为空! ", aObject.getName()));
        sb.append("\n");
      } else {
        // 对象Code限制非法字符
        if (!conformToNaminGspecification(aObject.getCode())) {
          sb.append(String.format("对象 '%1$s' 的 [编号] 属性必须以英文字母或下划线开头, 并且只能由英文字母、数字、下划线(_)组成! ",
              aObject.getName()));
          sb.append("\n");
        }
      }
      if (CheckInfoUtil.checkNull(aObject.getName())) {
        sb.append(String.format("对象 '%1$s' 的名称不能为空! ", aObject.getCode()));
        sb.append("\n");
      }
//      if (aObject.getCode().length() > 30) {
//        sb.append(String.format("对象 '%1$s' 的编号的长度不能超过30! ", aObject.getName()));
//        sb.append("\n");
//      }
    }

    //编号不允许重复
    for (int i = 0; i < aObjectList.size() - 1; i++) {
      IGspCommonObject firstObj = aObjectList.get(i);
      for (int j = i + 1; j < aObjectList.size(); j++) {
        IGspCommonObject secondObj = aObjectList.get(j);
        if (firstObj.getCode().compareToIgnoreCase(secondObj.getCode()) == 0) {
          sb.append(String
              .format("对象 '%1$s' 和对象'%2$s'的编号相同，请修改。", firstObj.getName(), secondObj.getName()));
          sb.append("\n");
        }
      }
    }

    if (sb.length() > 0) {
      sb.setLength(sb.length() - 1);
      throwValidateException(sb.toString());
      validateRez = false;
    }

    return validateRez;
  }

  ///#endregion

  ///#region 字段

  /**
   * 检验所有字段[编号][名称][标签]不允许为空，同一对象上所有字段的[编号][名称][标签]不允许重复
   */
  private boolean validateElement() {
    boolean validateRez = true;
    StringBuilder sb = new StringBuilder();

    ArrayList<IGspCommonObject> aObjectList = vm.getAllObjectList();
    for (IGspCommonObject aObject : aObjectList) {
      java.util.ArrayList<IGspCommonElement> allElementList = aObject.getAllElementList(false);

      if (allElementList != null && allElementList.size() > 0) {
        //字段[编号][名称][标签]不允许为空
        for (IGspCommonElement element : allElementList) {
          validateElementBasicInfo(element, sb, aObject.getName(), FIELD);
        }

        //同一对象上所有字段的[编号][名称][标签]不允许重复
        for (int i = 0; i < allElementList.size() - 1; i++) {
          IGspCommonElement firstElement = allElementList.get(i);
          for (int j = i + 1; j < allElementList.size(); j++) {
            IGspCommonElement secondElement = allElementList.get(j);
            if (firstElement.getCode().equals(secondElement.getCode()) && firstElement
                .getBelongObject().getID().equals(secondElement.getBelongObject().getID())) {
              sb.append(String.format("对象 '%1$s' 中字段 '%2$s' 和字段 '%3$s' 的 [编号] 属性不允许重复! ",
                  firstElement.getBelongObject().getName(), firstElement.getName(),
                  secondElement.getName()));
              sb.append("\n");
            }
            if (firstElement.getName().equals(secondElement.getName()) && firstElement
                .getBelongObject().getID().equals(secondElement.getBelongObject().getID())) {
              sb.append(String.format("对象 '%1$s' 中字段 '%2$s' 和字段 '%3$s' 的 [名称] 属性不允许重复! ",
                  firstElement.getBelongObject().getName(), firstElement.getName(),
                  secondElement.getName()));
              sb.append("\n");
            }
            if (firstElement.getLabelID().equals(secondElement.getLabelID()) && firstElement
                .getBelongObject().getID().equals(secondElement.getBelongObject().getID())) {
              sb.append(String.format("对象 '%1$s' 中字段 '%2$s' 和字段 '%3$s' 的 [标签] 属性不允许重复! ",
                  firstElement.getBelongObject().getName(), firstElement.getName(),
                  secondElement.getName()));
              sb.append("\n");
            }
          }
        }

        // 结合beObject检查
        checkWithBeObject((GspViewObject) ((aObject instanceof GspViewObject) ? aObject : null),
            allElementList);

      }
    }
    if (sb.length() > 0) {
      sb.setLength(sb.length() - 1);
      throwValidateException(sb.toString());
      validateRez = false;
    }
    return validateRez;
  }

  public String getFormat(String formatStr) {
    return null;
  }

  private void validateElementBasicInfo(IGspCommonField element, StringBuilder sb, String objName,
      String errorMessage) {
    if (CheckInfoUtil.checkNull(element.getCode())) {
      sb.append(String.format(errorMessage + " 的 [编号] 属性不允许为空! ", objName, element.getName()));
      sb.append("\n");
    } else {
      // 字段Code限制非法字符
      if (!conformToNaminGspecification(element.getCode())) {
        sb.append(String
            .format(errorMessage + " 的 [编号] 属性必须以英文字母或下划线开头, 并且只能由英文字母、数字、下划线(_)组成! ", objName,
                element.getName()));
        sb.append("\n");
      }
    }
    if (CheckInfoUtil.checkNull(element.getName())) {
      sb.append(String.format(errorMessage + " 的 [名称] 属性不允许为空! ", objName, element.getCode()));
      sb.append("\n");
    }

    if (CheckInfoUtil.checkNull(element.getLabelID()) || CheckInfoUtil
        .checkNull(element.getLabelID().trim())) {
      sb.append(String.format(errorMessage + " 的 [标签] 属性不允许为空! ", objName, element.getName()));
      sb.append("\n");
    } else {
      // LabelID在表单和报表中用作XML的标签，要限制非法字符
      String re = "^[A-Za-z_][A-Za-z_\\d-.]*$";
      Pattern pattern = Pattern.compile(re);
      Matcher matcher = pattern.matcher(element.getLabelID().trim());
      if (!getRegx(re, element.getLabelID().trim())) {
        sb.append(String
            .format(errorMessage + " 的 [标签] 属性\n必须以英文字母或下划线开头, 并且只能由英文字母、数字、下划线(_)、连线(-)和点(.)组成! ",
                objName, element.getName()));
        sb.append("\n");
      }
    }

    if (element.getObjectType() == GspElementObjectType.Enum) {
      if (element.getContainEnumValues().size() == 0) {
        sb.append(String
            .format(errorMessage + "的 [对象类型] 属性为枚举, [枚举] 属性不允许为空! ", objName, element.getName()));
        sb.append("\n");
      }

      // 枚举类型字段，校验默认值为枚举编号
      if (!CheckInfoUtil.checkNull(element.getDefaultValue())) {
        String defaultValue = element.getDefaultValue();
        boolean isEnumKey = false;
        for (GspEnumValue enumValue : element.getContainEnumValues()) {
          if (defaultValue.equals(enumValue.getValue())) {
            isEnumKey = true;
          }
        }
        if (!isEnumKey) {
          sb.append(String
              .format(errorMessage + "的 [对象类型] 属性为枚举, [默认值] 应为枚举编号。 ", objName, element.getName()));
        }
      }
      // 枚举类型字段，非必填
      if (element.getIsRequire()) {
        sb.append(String
            .format(errorMessage + "的 [对象类型] 属性为枚举, [是否必填] 属性应为否。 ", objName, element.getName()));
        sb.append("\n");
      }
    }

    if(!element.getIsVirtual()) { //资金在be上创建了长度为0的虚拟字段(因不希望长度校验), vo上校验临时增加兼容
      if (element.getMDataType() == GspElementDataType.Decimal) {
        if (element.getLength() == 0) {
          sb.append(String
              .format(errorMessage + "的[数据类型] 为[浮点数字]，其 [长度] 不可为0. ", objName, element.getName()));
          sb.append("\n");
        }

        if (element.getPrecision() == 0) {
          sb.append(String
              .format(errorMessage + "的[数据类型] 为[浮点数字]，其 [精度] 不可为0. ", objName, element.getName()));
          sb.append("\n");
        }
      }

      if (element.getMDataType() == GspElementDataType.String) {
        if (element.getLength() == 0) {
          sb.append(String
              .format(errorMessage + "的[数据类型] 为[文本]，其 [长度] 不可为0. ", objName, element.getName()));
          sb.append("\n");
        }
      }
    }
    // 默认值类型校验
    String message = validateElementDefaultValue(element, objName, errorMessage);
    if (message.length() > 0) {
      sb.append(String.format(message));
      sb.append("\n");
    }
  }

  /**
   * 正则化判断证书小数
   */
  private boolean getRegx(String regex, String regexStr) {
    Pattern pattern = Pattern.compile(regex);
    Matcher matcher = pattern.matcher(regexStr);
    boolean isRegex = matcher.matches();
    return isRegex;
  }

  private String validateElementDefaultValue(IGspCommonField ele, String objName,
      String errorMessage) {
    StringBuilder sb = new StringBuilder();
    String reInt = "^-?\\d+$"; //判断整数，负值也是整数
    String reDecimalString = String
        .format("^(([0-9]+\\.[0-9]{0,%1$s})|([0-9]*\\.[0-9]{0,%1$s})|([1-9][0-9]+)|([0-9]))$",
            ele.getPrecision());

    // 20190523-整型枚举可设置枚举编号为默认值；关联/udt默认值暂不支持；
    if (ele.getObjectType() != GspElementObjectType.None) {
      return sb.toString();
    }

    boolean isValidate = true;
    GspElementDataType type = ele.getMDataType();
    String value = ele.getDefaultValue();
    if(ele.getDefaultValueType()== ElementDefaultVauleType.Expression) {
      validateElementExpression(ele, sb, objName);
      return sb.toString();
    }
    if (!CheckInfoUtil.checkNull(value)) {
      switch (type) {
        case String:
        case Text:
          break;
        case Integer:
          if (getRegx(reInt, value)) {
            isValidate = true;
          } else {
            isValidate = false;
          }
          break;
        case Decimal:
          if (getRegx(reDecimalString, value)) {
            isValidate = true;
          } else {
            //isValidate = false;
            sb.append(String
                .format(errorMessage + "的[默认值] 与[数据类型] 不匹配，请检查是否为[浮点数字]，请检查[精度]是否匹配! ", objName,
                    ele.getName()));
            sb.append("\n");
            return sb.toString();
          }
          break;
        case Date:
          try {
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
            Date date=sdf.parse(value);
            isValidate = true;
          } catch (java.lang.Exception e) {
            isValidate = false;
          }
          break;
        case DateTime:
          try {
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            Date date=sdf.parse(value);
            isValidate = true;
          } catch (java.lang.Exception e) {
            isValidate = false;
          }
          break;
        case Boolean:
          if (value.toUpperCase().equals((new String("True")).toUpperCase()) || value.toUpperCase()
              .equals((new String("False")).toUpperCase())) {
            isValidate = true;
          } else {
            isValidate = false;
          }
          break;
        case Binary:
          if (value.trim().equals("")) {
            isValidate = true;
          } else {
            isValidate = false;
          }
          break;
        default:
          break;
      }
    }
    if (!isValidate) {
      sb.append(String.format(errorMessage + "的 [默认值] 与 [数据类型] 不匹配! ", objName, ele.getName()));
      sb.append("\n");
    }
    return sb.toString();
  }

  /**
   * 校验be字段表达式类型默认值校验
   *
   * @param ele be字段
   * @param sb 错误提示
   * @param aObjectName be名称
   */
  private void validateElementExpression(IGspCommonField ele, StringBuilder sb, String aObjectName) {
    String expression = ele.getDefaultValue();
    if (ExpressionVariableCheckUtil.isDateType(expression)) {
      if (ele.getMDataType() == GspElementDataType.Date || ele.getMDataType() == GspElementDataType.DateTime) {
        return;
      }
      sb.append(String.format(EXPRESSION + "的数据类型与表达式类型不相符,请选择文本类型的表达式。", aObjectName, ele.getName()));
      sb.append("\n");
    }
    if (ExpressionVariableCheckUtil.isTextType(expression)) {
      if (ele.getMDataType() == GspElementDataType.String || ele.getMDataType() == GspElementDataType.Text) {
        return;
      }
      sb.append(String.format(EXPRESSION + "的数据类型与表达式类型不相符,请选择日期类型的表达式。", aObjectName, ele.getName()));
      sb.append("\n");
    }
  }

  /**
   * 结合bizObject检查
   */
  private void checkWithBeObject(GspViewObject aObject,
      java.util.ArrayList<IGspCommonElement> allElementList) {
    // 虚拟对象无映射bizObj
    if (aObject.getIsVirtual()
        || aObject.getMapping().getSourceType() != GspVoObjectSourceType.BeObject) {
      return;
    }

    // 其他be源暂不检查
    if (!aObject.getMapping().getTargetMetadataId().equals(be.getID())) {
      return;
    }

    IGspCommonObject beObject = be.getAllObjectList().stream().filter(
        item -> item.getID().equals(((GspViewObject) aObject).getMapping().getTargetObjId()))
        .findFirst().orElse(
            null);//.FirstOrDefault(item => String.equals(item.ID, ((GspViewObject)aObject).getMapping().TargetObjId));
    if (beObject == null) {
      throwValidateException(
          "对象" + aObject.getName() + "在业务实体上无映射对象，业务实体对象的id=" + aObject.getMapping()
              .getTargetObjId() + ",请检查是否已删除。");
    }
    java.util.ArrayList<IGspCommonElement> beElementList = beObject.getAllElementList(false);

    // vm字段长度不得大于映射的be字段长度
    for (IGspCommonElement element : allElementList) {

      GspViewModelElement vmEle = (GspViewModelElement) element;
      if (vmEle.getIsVirtualViewElement()
          || vmEle.getMapping().getSourceType() != GspVoElementSourceType.BeElement
          || !vmEle.getMapping().getTargetMetadataId().equals( be.getID())) {
        continue;
      }

      GspBizEntityElement beEle = (GspBizEntityElement) beElementList.stream().filter(
          item -> item.getID()
              .equals(((GspViewModelElement) element).getMapping().getTargetObjId())).findFirst()
          .orElse(null);
      if (beEle == null) {

        GspBizEntityElement beEle2 = (GspBizEntityElement) be
            .findElementById(((GspViewModelElement) element).getMapping().getTargetObjId());
        // 当前字段不是当前bizObj引入，不抛异常
        if (beEle2 != null) {
          continue;
        }
        throwValidateException(
            "对象" + aObject.getName() + "上的字段" + element.getName() + "在业务实体上无映射字段，业务实体字段的id="
                + ((GspViewModelElement) element).getMapping().getTargetObjectId() + ",请检查是否已删除。");
      } else {
        if (element.getLength() > beEle.getLength()) {
          throwValidateException(
              "对象" + aObject.getName() + "上的字段" + element.getName() + "的[长度]不能大于业务实体上字段长度" + beEle
                  .getLength() + "。");
        }
        if (element.getPrecision() > beEle.getPrecision()) {
          throwValidateException(
              "对象" + aObject.getName() + "上的字段" + element.getName() + "的[精度]不能大于业务实体上字段精度" + beEle
                  .getPrecision() + "。");
        }
      }
    }
  }

  ///#endregion

  ///#region 操作

  /**
   * [操作]视图对象操作
   */
  private boolean validateVmActions() {
    java.util.ArrayList<ViewModelAction> actions = vm.getActions();
    String errorMessage = String.format(OPT_CDPACTION);
    boolean validateRez = true;
    StringBuilder sb = new StringBuilder();
    validateRez = validateActionsBasicInfo(actions, errorMessage, sb);

    if (!vm.getIsVirtual()
        && vm.getMainObject().getMapping().getSourceType() == GspVoObjectSourceType.BeObject) {

      BizMgrActionCollection mgrActions = be.getBizMgrActions();
      //④检查be带出操作是否已删除
      if (actions.size() > 0) {
        for (int i = 0; i < actions.size(); i++) {

          ViewModelAction vmAction = actions.get(i);
          if (vmAction.getType() == ViewModelActionType.BEAction) {
            BizMgrAction mgrAction = (BizMgrAction) mgrActions.stream()
                .filter(item -> item.getID().equals(vmAction.getMapping().getTargetObjId()))
                .findFirst().orElse(null);//Find(item => item.ID == vmAction.Mapping.TargetObjId);
            if (mgrAction == null) {
              throwValidateException(
                  "操作'" + vmAction.getName() + "在业务实体上无映射操作，业务实体自定义操作的id=" + vmAction.getMapping()
                      .getTargetObjId() + ",请检查是否已删除。");
              validateRez = false;
            }
          }
          else {
            String errorMsg = validComp(vmAction);
            if(!StringUtils.isEmpty(errorMsg)){
              throwValidateException(errorMsg);
            }
          }
        }
      }
    }

    if (sb.length() > 0) {
      throwValidateException(sb.toString());
      validateRez = false;
    }
    return validateRez;
  }

  private String validComp(ViewModelAction vmAction){
    StringBuilder sb = new StringBuilder();

    if(!(vmAction instanceof  MappedCdpActionBase)){
      return "";
    }
    MappedCdpActionBase mappedCdpActionBase = (MappedCdpActionBase)vmAction;
    if(mappedCdpActionBase.getIsGenerateComponent() || StringUtils.isEmpty(mappedCdpActionBase.getComponentEntityId())){
      return "";
    }
    //如果是引用已有构件,需要做参数校验
    RefCommonService metadataService=SpringBeanUtils.getBean(RefCommonService.class);
    GspMetadata metadata = metadataService.getRefMetadata(((MappedCdpActionBase) vmAction).getComponentEntityId());
    if(metadata == null){
      sb.append(String.format("动作'%1$s'对应的构件元数据不存在!", vmAction.getName()));
      sb.append("\n");
      return sb.toString();
    }
    ICompParameterCollection compParameterCollection = null;
    if(metadata.getContent() instanceof VMComponent) {
      VMComponent component = (VMComponent) metadata.getContent();
       compParameterCollection = component.getMethod().getCompParameterCollection();
      int oprParSize = vmAction.getParameterCollection() == null ? 0 : vmAction.getParameterCollection().getCount();
      int compParSize = compParameterCollection == null ? 0 :compParameterCollection.getCount();
      if(oprParSize != compParSize){
        sb.append(String.format("动作'%1$s'的参数个数为:%2$s,对应构件上参数个数为%3$s，请确认!", vmAction.getName(), oprParSize, compParSize));
        sb.append("\n");
        return sb.toString();
      }
    }
    if(!mappedCdpActionBase.getIsGenerateComponent()){
      for(int i=0; i< vmAction.getParameterCollection().getCount(); i++){
        IViewModelParameter viewModelParameter = vmAction.getParameterCollection().getItem(i);
        ICompParameter compParameter = compParameterCollection.getItem(i);
        //引用构件的才校验
        sb.append(validVMCompParameter(viewModelParameter, compParameter, vmAction));
      }
      sb.append(validReturnValue(vmAction, (VMComponent) metadata.getContent()));
    }
    return sb.toString();
  }

  private String validReturnValue(ViewModelAction vmAction, VMComponent vmComponent){
    StringBuilder sb = new StringBuilder();
    ViewModelReturnValue vmReturnValue = vmAction.getReturnValue();
    ReturnValue returnValue = vmComponent.getVmMethod().getReturnValue();
    //返回值为空 不校验
    if("void".equalsIgnoreCase(vmReturnValue.getDotnetClassName()) && "void".equalsIgnoreCase(returnValue.getDotnetClassName()))
      return "";

    if(!StringUtils.equalsIgnoreCase(vmReturnValue.getClassName(), returnValue.getClassName())){
      sb.append(String.format("动作'%1$s'中返回类型和构件不一致", vmAction.getName()));
    }
    if(vmReturnValue.getCollectionParameterType().getValue() != returnValue.getParameterCollectionType().getValue()){
      sb.append(String.format("动作'%1$s'中返回值集合类型和构件不一致", vmAction.getName()));
    }
    return sb.toString();
  }
  private String validVMCompParameter(IViewModelParameter viewModelParameter, ICompParameter compParameter, ViewModelAction vmActionBase){
    StringBuilder sb = new StringBuilder();
    if(!StringUtils.equalsIgnoreCase(viewModelParameter.getParamCode(), compParameter.getParamCode())){
      sb.append(String.format("动作'%1$s'中的参数'%2$s'和构件参数'%3$s'的[编号] 属性不一致", vmActionBase.getName(), viewModelParameter.getParamCode(), compParameter.getParamCode()));
    }
    if(!StringUtils.equalsIgnoreCase(viewModelParameter.getClassName(), compParameter.getClassName())){
      sb.append(String.format("动作'%1$s'中的参数'%2$s'和构件参数的[类型] 属性不一致，类型分别为'%3$s','%4$s'", vmActionBase.getName(), viewModelParameter.getParamCode(),viewModelParameter.getClassName(), compParameter.getClassName()));
    }
    return sb.toString();
  }

  private boolean validateActionsBasicInfo(java.util.ArrayList<ViewModelAction> actions,
      String errorMessage, StringBuilder sb) {
    boolean validateRez = true;

    //①必填项
    sb.append(String.format(validateOperationBasicInfo(errorMessage, actions)));
    if (sb.length() > 0) {
      throwValidateException(sb.toString());
      validateRez = false;
    }
    //②编号重复
    sb.append(String.format(validateOperationCodeRepeat(errorMessage, actions)));
    if (sb.length() > 0) {
      throwValidateException(sb.toString());
      validateRez = false;
    }
    //③参数及返回值校验
    sb.append(String.format(validateActionParas(errorMessage, actions)));
    if (sb.length() > 0) {
      throwValidateException(sb.toString());
      validateRez = false;
    }
    return validateRez;
  }

  private boolean validateHelpActions() {
    boolean validateRez = true;
    StringBuilder sb = new StringBuilder();
    java.util.ArrayList<ViewModelAction> actions = new java.util.ArrayList<ViewModelAction>();

    ArrayList<IGspCommonElement> elementList = vm.getAllElementList(true);

    for (IGspCommonElement item : elementList) {
      GspViewModelElement element = (GspViewModelElement) item;
      if (element.getHelpActions() != null) {

        for (ViewModelAction action : element.getHelpActions()) {
          actions.add(action);
        }
      }

    }
    String errorMessage = String.format(OPT_CDPACTION);
    //①必填项
    sb.append(String.format(validateOperationBasicInfo(errorMessage, actions)));
    if (sb.length() > 0) {
      throwValidateException(sb.toString());
      validateRez = false;
    }
    //②编号重复
    sb.append(String.format(validateOperationCodeRepeat(errorMessage, actions)));
    if (sb.length() > 0) {
      throwValidateException(sb.toString());
      validateRez = false;
    }

    return validateRez;
  }

  /**
   * [操作]编号重复
   */
  private String validateOperationCodeRepeat(String errorMessage,
      java.util.ArrayList<ViewModelAction> operations) {
    StringBuilder sb = new StringBuilder();
    if (operations != null && operations.size() > 0) {
      for (int i = 0; i < operations.size() - 1; i++) {
        ViewModelAction firstOperation = operations.get(i);
        for (int j = i + 1; j < operations.size(); j++) {
          ViewModelAction secondOperation = operations.get(j);
          if (firstOperation.getCode().equals(secondOperation.getCode())) {
            String message = String
                .format(errorMessage + "'%1$s'与'%2$s'的编号重复。", firstOperation.getName(),
                    secondOperation.getName());
            sb.append("\n");
            return message;
          }
        }
      }
    }
    return sb.toString();
  }

  /**
   * [操作]编号名称为空
   */
  private String validateOperationBasicInfo(String errorMessage,
      java.util.ArrayList<ViewModelAction> oprs) {
    if (oprs == null || oprs.isEmpty()) {
      return "";
    }
    StringBuilder sb = new StringBuilder();

    for (ViewModelAction opr : oprs) {
      if (CheckInfoUtil.checkNull(opr.getCode())) {
        sb.append(
            String.format(errorMessage + String.format("'%1$s'的 [编号] 属性不允许为空! ", opr.getName())));
        sb.append("\n");
      } else {
        // 操作Code限制非法字符
        if (!conformToNaminGspecification(opr.getCode())) {
          sb.append(String.format(errorMessage + String
              .format("'%1$s'的 [编号] 属性必须以英文字母或下划线开头, 并且只能由英文字母、数字、下划线(_)组成! ", opr.getName())));
          sb.append("\n");
        }
      }
      if (CheckInfoUtil.checkNull(opr.getName())) {
        sb.append(
            String.format(errorMessage + String.format("'%1$s'的 [名称] 属性不允许为空! ", opr.getCode())));
        sb.append("\n");
      }
    }
    return sb.toString();
  }

  /**
   * [操作]编号重复
   */
  private String validateCommonOperationCodeRepeat(String errorMessage,
      ArrayList<CommonOperation> operations) {
    StringBuilder sb = new StringBuilder();
    if (operations != null && operations.size() > 0) {
      for (int i = 0; i < operations.size() - 1; i++) {
        CommonOperation firstOperation = operations.get(i);
        for (int j = i + 1; j < operations.size(); j++) {
          CommonOperation secondOperation = operations.get(j);
          if (firstOperation.getCode().equals(secondOperation.getCode())) {
            String message = String
                .format(errorMessage + "'%1$s'与'%2$s'的编号重复。", firstOperation.getName(),
                    secondOperation.getName());
            sb.append("\n");
            return message;
          }
        }
      }
    }
    return sb.toString();
  }

  /**
   * [操作]编号名称为空
   */
  private String validateCommonOperationBasicInfo(String errorMessage,
      ArrayList<CommonOperation> oprs) {
    if (oprs == null || oprs.size() == 0) {
      return "";
    }
    StringBuilder sb = new StringBuilder();

    for (CommonOperation opr : oprs) {
      if (CheckInfoUtil.checkNull(opr.getCode())) {
        sb.append(
            String.format(errorMessage + String.format("'%1$s'的 [编号] 属性不允许为空! ", opr.getName())));
        sb.append("\n");
      } else {
        // 操作Code限制非法字符
        if (!conformToNaminGspecification(opr.getCode())) {
          sb.append(String.format(errorMessage + String
              .format("'%1$s'的 [编号] 属性必须以英文字母或下划线开头, 并且只能由英文字母、数字、下划线(_)组成! ", opr.getName())));
          sb.append("\n");
        }
      }
      if (CheckInfoUtil.checkNull(opr.getName())) {
        sb.append(
            String.format(errorMessage + String.format("'%1$s'的 [名称] 属性不允许为空! ", opr.getCode())));
        sb.append("\n");
      }
    }
    return sb.toString();
  }

  /**
   * [操作]-action-参数
   */
  private String validateActionReturnValue(ViewModelAction opr, String errorMessage) {
    StringBuilder sb = new StringBuilder();
    ViewModelReturnValue returnValue = opr.getReturnValue();
    if (returnValue != null && returnValue.getParameterType() == VMParameterType.Custom) {
//			if (VmManagerService.CreatDotnetModule(metaPath))
//			{
//				if (CheckInfoUtil.checkNull(returnValue.getClassName()) || CheckInfoUtil.checkNull(returnValue.getAssembly()))
//				{
//					sb.append(String.format("N版元数据工程，" + errorMessage + "'%1$s'中的返回值的 [类型] 为自定义类型，请完善其程序集名、类名。", opr.getName()));
//					sb.append("\n");
//				}
//			}
      if (VmManagerService.creatJavaModule(metaPath)) {
        if (opr instanceof MappedCdpActionBase && !((MappedCdpActionBase) opr)
            .getIsGenerateComponent()) {

        } else {
          if (CheckInfoUtil.checkNull(returnValue.getClassName())) {
            sb.append(String
                .format("J版元数据工程，" + errorMessage + "'%1$s'中的返回值的 [类型] 为自定义类型，请完善其Java类名。",
                    opr.getName()));
            sb.append("\n");
          }
        }
      }
    }
    return sb.toString();
  }


  /**
   * 校验动作参数及返回值
   */
  private String validateActionParas(String errorMessage,
      java.util.ArrayList<ViewModelAction> actions) {
    StringBuilder sb = new StringBuilder();
    if (actions != null && actions.size() > 0) {

      for (ViewModelAction action : actions) {
        sb.append(String.format(validateActionParas((ViewModelAction) action, errorMessage)));
        sb.append(String.format(validateActionReturnValue((ViewModelAction) action, errorMessage)));
        sb.append(String.format(validateActionComponent((ViewModelAction) action, errorMessage)));
      }
    }
    return sb.toString();
  }


  private String validateActionComponent(ViewModelAction action,String errorMessage) {
    StringBuilder sb = new StringBuilder();
    if(action instanceof MappedCdpAction){
      MappedCdpAction mappedCdpAction = (MappedCdpAction)action;
      if(mappedCdpAction.getIsGenerateComponent() || StringUtils.isEmpty(mappedCdpAction.getComponentEntityId()))
        return "";
      RefCommonService metadataService=SpringBeanUtils.getBean(RefCommonService.class);
      GspMetadata metadata = metadataService.getRefMetadata(((MappedCdpActionBase) action).getComponentEntityId());
      if(metadata == null){
        sb.append(String.format("动作'%1$s'对应的构件元数据不存在!", action.getName()));
        sb.append("\n");
        return sb.toString();
      }
    }
    return sb.toString();
  }

  private String validateActionParas(ViewModelAction opr, String message) {
    StringBuilder sb = new StringBuilder();
    //参数编号名称不可为空

    for (Object para : opr.getParameterCollection()) {
      if (CheckInfoUtil.checkNull(((IViewModelParameter) para).getParamCode())) {
        sb.append(String.format(message + String
            .format("'%1$s'中的参数'%2$s'的 [编号] 属性不允许为空! ", opr.getName(),
                ((IViewModelParameter) para).getParamName())));
        sb.append("\n");
      } else {
        // 参数编号Code限制非法字符
        if (!conformToNaminGspecification(((IViewModelParameter) para).getParamCode())) {
          sb.append(String.format(message + String
              .format("'%1$s'中的参数'%2$s'的[编号] 属性必须以英文字母或下划线开头, 并且只能由英文字母、数字、下划线(_)组成! ",
                  opr.getName(), ((IViewModelParameter) para).getParamName())));
          sb.append("\n");
        }
      }
      if (CheckInfoUtil.checkNull(((IViewModelParameter) para).getParamName())) {
        sb.append(String.format(message + String
            .format("'%1$s'中的参数'%2$s'的 [名称] 属性不允许为空! ", opr.getName(),
                ((IViewModelParameter) para).getParamCode())));
        sb.append("\n");
      }
      if (((IViewModelParameter) para).getParameterType() == VMParameterType.Custom) {
//				if (VmManagerService.CreatDotnetModule(metaPath))
//				{
//					if (CheckInfoUtil.checkNull(para.ClassName) || CheckInfoUtil.checkNull(para.Assembly))
//					{
//						sb.append(String.format("N版元数据工程，" + message + "'%1$s'中的参数'%2$s' [参数类型] 为自定义类型，请完善其程序集名、类名。", opr.getName(), para.ParamName));
//						sb.append("\n");
//					}
//				}
        if (VmManagerService.creatJavaModule(metaPath)) {
          if (opr instanceof MappedCdpActionBase && !((MappedCdpActionBase) opr)
              .getIsGenerateComponent()) {

          } else {
            if (CheckInfoUtil.checkNull(((IViewModelParameter) para).getClassName())) {
              sb.append(String
                  .format("J版元数据工程，" + message + "'%1$s'中的参数'%2$s' [参数类型] 为自定义类型，请完善其Java类名。",
                      opr.getName(), ((IViewModelParameter) para).getParamName()));
              sb.append("\n");
            }
          }
        }
      }
    }
    if (sb.length() > 0) {
      return sb.toString();
    }

    //参数编号不可重复
    if (opr.getParameterCollection() != null && opr.getParameterCollection().getCount() > 0) {
      for (int i = 0; i < opr.getParameterCollection().getCount() - 1; i++) {
        IViewModelParameter firstPara = opr.getParameterCollection().getItem(i);
        for (int j = i + 1; j < opr.getParameterCollection().getCount(); j++) {
          IViewModelParameter secondPara = opr.getParameterCollection().getItem(j);
          if (firstPara.getParamCode().equals(secondPara.getParamCode())) {
            sb.append(String
                .format(message + "'%1$s'中的参数'%2$s'和参数'%3$s'的[编号] 属性不允许重复", opr.getName(),
                    firstPara.getParamName(), secondPara.getParamName()));
            sb.append("\n");
          }
        }
      }
    }
    return sb.toString();
  }

  ///#endregion

  ///#region 扩展操作

  /**
   * 校验扩展操作
   */
  private boolean validateDataExtendInfo() {
    StringBuilder sb = new StringBuilder();

    boolean validateRez =
        validateExtendActionsBasicInfo(vm.getDataExtendInfo().getDataMappingActions(), "数据Mapping",
            sb)
            && validateExtendActionsBasicInfo(vm.getDataExtendInfo().getBeforeQueryActions(),
            "查询数据前", sb)
            && validateExtendActionsBasicInfo(vm.getDataExtendInfo().getQueryActions(), "查询数据", sb)
            && validateExtendActionsBasicInfo(vm.getDataExtendInfo().getAfterQueryActions(),
            "查询数据后", sb)
            && validateExtendActionsBasicInfo(vm.getDataExtendInfo().getBeforeRetrieveActions(),
            "检索数据前", sb)
            && validateExtendActionsBasicInfo(vm.getDataExtendInfo().getRetrieveActions(), "检索数据",
            sb)
            && validateExtendActionsBasicInfo(vm.getDataExtendInfo().getAfterRetrieveActions(),
            "检索数据后", sb)
            && validateExtendActionsBasicInfo(vm.getDataExtendInfo().getBeforeModifyActions(),
            "修改数据前", sb)
            && validateExtendActionsBasicInfo(vm.getDataExtendInfo().getModifyActions(), "修改数据", sb)
            && validateExtendActionsBasicInfo(vm.getDataExtendInfo().getAfterModifyActions(),
            "修改数据后", sb)
            && validateExtendActionsBasicInfo(vm.getDataExtendInfo().getChangesetMappingActions(),
            "变更集Mapping", sb)
            && validateExtendActionsBasicInfo(vm.getDataExtendInfo().getBeforeCreateActions(),
            "新增数据前", sb)
            && validateExtendActionsBasicInfo(vm.getDataExtendInfo().getCreateActions(), "新增数据", sb)
            && validateExtendActionsBasicInfo(vm.getDataExtendInfo().getAfterCreateActions(),
            "新增数据后", sb)
            && validateExtendActionsBasicInfo(vm.getDataExtendInfo().getBeforeDeleteActions(),
            "删除数据前", sb)
            && validateExtendActionsBasicInfo(vm.getDataExtendInfo().getDeleteActions(), "删除数据", sb)
            && validateExtendActionsBasicInfo(vm.getDataExtendInfo().getAfterDeleteActions(),
            "删除数据后", sb)
            && validateExtendActionsBasicInfo(vm.getDataExtendInfo().getBeforeSaveActions(),
            "保存数据前", sb)
            && validateExtendActionsBasicInfo(
            vm.getDataExtendInfo().getDataReversalMappingActions(), "数据反向Mapping", sb)
            && validateExtendActionsBasicInfo(vm.getDataExtendInfo().getAfterSaveActions(), "保存数据后",
            sb)
            && validateExtendActionsBasicInfo(
            vm.getDataExtendInfo().getChangesetReversalMappingActions(), "变更集反向Mapping", sb)
            && validateExtendActionsBasicInfo(vm.getDataExtendInfo().getBeforeMultiDeleteActions(),
            "批量删除数据前", sb)
            && validateExtendActionsBasicInfo(vm.getDataExtendInfo().getMultiDeleteActions(),
            "批量删除数据", sb)
            && validateExtendActionsBasicInfo(vm.getDataExtendInfo().getAfterMultiDeleteActions(),
            "批量删除数据后", sb);

    return validateRez;
  }

  private boolean validateExtendActionsBasicInfo(java.util.ArrayList<ViewModelAction> actions,
      String currentActionType, StringBuilder sb) {
    if (actions.isEmpty()) {
      return true;
    }
    String errorMessage = String.format("扩展操作 [%1$s] 中的", currentActionType);
    return validateActionsBasicInfo(actions, errorMessage, sb);
  }

  ///#endregion

  ///#region 帮助前事件

  private String validateValueHelpConfigs(GspViewModel model) {
    StringBuilder sb = new StringBuilder();
    ValueHelpConfigCollection configs = model.getValueHelpConfigs();
    if (configs != null && configs.size() > 0) {
      for (int i = 0; i < configs.size() - 1; i++) {
        ValueHelpConfig firstOperation = configs.getItem(i);
        for (int j = i + 1; j < configs.size(); j++) {
          ValueHelpConfig secondOperation = configs.getItem(j);
          if (firstOperation.getElementId().equals(secondOperation.getElementId())) {
            String message = String.format(VALUEHELPCONFIG + "'%1$s'与'%2$s'的[ElementId]属性重复。",
                firstOperation.getElementId(), secondOperation.getElementId());
            sb.append("\n");
            return message;
          }
        }
      }

      for (ValueHelpConfig config : configs) {
        if (CheckInfoUtil.checkNull(config.getElementId())) {
          sb.append(String.format(VALUEHELPCONFIG + "'%1$s' 的 [ElementId] 属性不允许为空，请检查! ",
              config.getElementId()));
          sb.append("\n");
        }
        if (CheckInfoUtil.checkNull(config.getHelperId())) {
          sb.append(String.format(VALUEHELPCONFIG + "'%1$s' 的 [HelperId] 属性不允许为空，请检查! ",
              config.getElementId()));
          sb.append("\n");
        }
        if (config.getHelpExtend() != null && config.getHelpExtend().getBeforeHelp() != null
            && config.getHelpExtend().getBeforeHelp().size() > 0) {

          VMActionCollection actions = config.getHelpExtend().getBeforeHelp();

          String errorMessage = String.format(VALUEHELPACTION, config.getElementId());
          validateActionsBasicInfo(actions, errorMessage, sb);
        }
      }
    }
    sb.append(validateVariables(model));
    return sb.toString();
  }

  ///#endregion

  ///#region 通用工具

  /**
   * 是否符合命名规范 字母数字下划线组成,字母下划线开头
   */
  private boolean conformToNaminGspecification(String text) {
    String re = "^[A-Za-z_][A-Za-z_0-9]*$";

    Pattern pattern = Pattern.compile(re);
    Matcher matcher = pattern.matcher(text);
    return matcher.matches();
  }

  ///#endregion
}